home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
comm
/
mail
/
Mutt089src.lha
/
Mutt-0.89i-AMIGA
/
src
/
rx
/
rxhash.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-28
|
9KB
|
395 lines
/* Copyright (C) 1995, 1996 Tom Lord
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Tom Lord (lord@cygnus.com, lord@gnu.ai.mit.edu)
*/
#include "rxall.h"
#include "rxhash.h"
#ifdef __STDC__
static struct rx_hash *
default_hash_alloc (struct rx_hash_rules * rules)
#else
static struct rx_hash *
default_hash_alloc (rules)
struct rx_hash_rules * rules;
#endif
{
return (struct rx_hash *)malloc (sizeof (struct rx_hash));
}
#ifdef __STDC__
static struct rx_hash_item *
default_hash_item_alloc (struct rx_hash_rules * rules, void * value)
#else
static struct rx_hash_item *
default_hash_item_alloc (rules, value)
struct rx_hash_rules * rules;
void * value;
#endif
{
struct rx_hash_item * it;
it = (struct rx_hash_item *)malloc (sizeof (*it));
if (it)
{
it->data = value;
it->binding = 0;
}
return it;
}
#ifdef __STDC__
static void
default_free_hash (struct rx_hash * tab,
struct rx_hash_rules * rules)
#else
static void
default_free_hash (tab, rules)
struct rx_hash * tab;
struct rx_hash_rules * rules;
#endif
{
free ((char *)tab);
}
#ifdef __STDC__
static void
default_free_hash_item (struct rx_hash_item * item,
struct rx_hash_rules * rules)
#else
static void
default_free_hash_item (item, rules)
struct rx_hash_item * item;
struct rx_hash_rules * rules;
#endif
{
free ((char *)item);
}
#ifdef __STDC__
static int
default_eq (void * va, void * vb)
#else
static int
default_eq (va, vb)
void * va;
void * vb;
#endif
{
return va == vb;
}
#define EQ(rules) ((rules && rules->eq) ? rules->eq : default_eq)
#define HASH_ALLOC(rules) ((rules && rules->hash_alloc) ? rules->hash_alloc : default_hash_alloc)
#define FREE_HASH(rules) ((rules && rules->free_hash) ? rules->free_hash : default_free_hash)
#define ITEM_ALLOC(rules) ((rules && rules->hash_item_alloc) ? rules->hash_item_alloc : default_hash_item_alloc)
#define FREE_HASH_ITEM(rules) ((rules && rules->free_hash_item) ? rules->free_hash_item : default_free_hash_item)
static unsigned long rx_hash_masks[4] =
{
0x12488421,
0x96699669,
0xbe7dd7eb,
0xffffffff
};
/* hash to bucket */
#define JOIN_BYTE(H, B) (((H) + ((H) << 3) + (B)) & 0xf)
#define H2B(X) JOIN_BYTE (JOIN_BYTE (JOIN_BYTE ((X & 0xf), ((X>>8) & 0xf)), ((X>>16) & 0xf)), ((X>>24) & 0xf))
#define BKTS 16
/* Hash tables */
#ifdef __STDC__
struct rx_hash_item *
rx_hash_find (struct rx_hash * table,
unsigned long hash,
void * value,
struct rx_hash_rules * rules)
#else
struct rx_hash_item *
rx_hash_find (table, hash, value, rules)
struct rx_hash * table;
unsigned long hash;
void * value;
struct rx_hash_rules * rules;
#endif
{
rx_hash_eq eq = EQ (rules);
int maskc = 0;
long mask = rx_hash_masks [0];
int bucket = H2B(hash & mask);
while (RX_bitset_member (&table->nested_p, bucket))
{
table = (struct rx_hash *)(table->children [bucket]);
++maskc;
mask = rx_hash_masks[maskc];
bucket = H2B (hash & mask);
}
{
struct rx_hash_item * it;
it = (struct rx_hash_item *)(table->children[bucket]);
while (it)
if (eq (it->data, value))
return it;
else
it = it->next_same_hash;
}
return 0;
}
#ifdef __STDC__
static int
listlen (struct rx_hash_item * bucket)
#else
static int
listlen (bucket)
struct rx_hash_item * bucket;
#endif
{
int i;
for (i = 0; bucket; ++i, bucket = bucket->next_same_hash)
;
return i;
}
#ifdef __STDC__
static int
overflows (struct rx_hash_item * bucket)
#else
static int
overflows (bucket)
struct rx_hash_item * bucket;
#endif
{
return !( bucket
&& bucket->next_same_hash
&& bucket->next_same_hash->next_same_hash
&& bucket->next_same_hash->next_same_hash->next_same_hash);
}
#ifdef __STDC__
struct rx_hash_item *
rx_hash_store (struct rx_hash * table,
unsigned long hash,
void * value,
struct rx_hash_rules * rules)
#else
struct rx_hash_item *
rx_hash_store (table, hash, value, rules)
struct rx_hash * table;
unsigned long hash;
void * value;
struct rx_hash_rules * rules;
#endif
{
rx_hash_eq eq = EQ (rules);
int maskc = 0;
long mask = rx_hash_masks [0];
int bucket = H2B(hash & mask);
int depth = 0;
while (RX_bitset_member (&table->nested_p, bucket))
{
table = (struct rx_hash *)(table->children [bucket]);
++maskc;
mask = rx_hash_masks[maskc];
bucket = H2B(hash & mask);
++depth;
}
{
struct rx_hash_item * it;
it = (struct rx_hash_item *)(table->children[bucket]);
while (it)
if (eq (it->data, value))
return it;
else
it = it->next_same_hash;
}
{
if ( (depth < 3)
&& (overflows ((struct rx_hash_item *)table->children [bucket])))
{
struct rx_hash * newtab;
newtab = (struct rx_hash *) HASH_ALLOC(rules) (rules);
if (!newtab)
goto add_to_bucket;
rx_bzero ((char *)newtab, sizeof (*newtab));
newtab->parent = table;
{
struct rx_hash_item * them;
unsigned long newmask;
them = (struct rx_hash_item *)table->children[bucket];
newmask = rx_hash_masks[maskc + 1];
while (them)
{
struct rx_hash_item * save = them->next_same_hash;
int new_buck = H2B(them->hash & newmask);
them->next_same_hash = ((struct rx_hash_item *)
newtab->children[new_buck]);
((struct rx_hash_item **)newtab->children)[new_buck] = them;
them->table = newtab;
them = save;
++newtab->refs;
--table->refs;
}
((struct rx_hash **)table->children)[bucket] = newtab;
RX_bitset_enjoin (&table->nested_p, bucket);
++table->refs;
table = newtab;
bucket = H2B(hash & newmask);
}
}
}
add_to_bucket:
{
struct rx_hash_item * it = ((struct rx_hash_item *)
ITEM_ALLOC(rules) (rules, value));
if (!it)
return 0;
it->hash = hash;
it->table = table;
/* DATA and BINDING are to be set in hash_item_alloc */
it->next_same_hash = (struct rx_hash_item *)table->children [bucket];
((struct rx_hash_item **)table->children)[bucket] = it;
++table->refs;
return it;
}
}
#ifdef __STDC__
void
rx_hash_free (struct rx_hash_item * it, struct rx_hash_rules * rules)
#else
void
rx_hash_free (it, rules)
struct rx_hash_item * it;
struct rx_hash_rules * rules;
#endif
{
if (it)
{
struct rx_hash * table = it->table;
unsigned long hash = it->hash;
int depth = (table->parent
? (table->parent->parent
? (table->parent->parent->parent
? 3
: 2)
: 1)
: 0);
int bucket = H2B (hash & rx_hash_masks [depth]);
struct rx_hash_item ** pos
= (struct rx_hash_item **)&table->children [bucket];
while (*pos != it)
pos = &(*pos)->next_same_hash;
*pos = it->next_same_hash;
FREE_HASH_ITEM(rules) (it, rules);
--table->refs;
while (!table->refs && depth)
{
struct rx_hash * save = table;
table = table->parent;
--depth;
bucket = H2B(hash & rx_hash_masks [depth]);
--table->refs;
table->children[bucket] = 0;
RX_bitset_remove (&table->nested_p, bucket);
FREE_HASH (rules) (save, rules);
}
}
}
#ifdef __STDC__
void
rx_free_hash_table (struct rx_hash * tab, rx_hash_freefn freefn,
struct rx_hash_rules * rules)
#else
void
rx_free_hash_table (tab, freefn, rules)
struct rx_hash * tab;
rx_hash_freefn freefn;
struct rx_hash_rules * rules;
#en